package com.media.selector.media.model.loader

import android.content.Context
import android.database.Cursor
import android.database.MatrixCursor
import android.database.MergeCursor
import android.provider.MediaStore
import androidx.loader.content.CursorLoader
import com.media.selector.media.model.SelectionSpec
import com.media.selector.media.model.entity.MediaEntity

/**
 * date        ：2020/5/12
 * author      ：蒙景博
 * description ：
 */
class AlbumMediaLoader private constructor(
    context: Context,
    selection: String?,
    selectionArgs: Array<String>?,
    private val isCapture: Boolean
) : BaseCursorLoader(
    context,
    PROJECTION,
    selection,
    selectionArgs,
    BUCKET_ORDER_BY
) {

    companion object {

        private val PROJECTION = arrayOf(MediaStore.Files.FileColumns._ID, MediaStore.MediaColumns.DISPLAY_NAME, MediaStore.MediaColumns.MIME_TYPE, MediaStore.MediaColumns.SIZE, "duration")

        // === params for album ALL && showSingleMediaType: false ===
        private const val SELECTION_ALL = "(${MediaStore.Files.FileColumns.MEDIA_TYPE}=? $OR ${MediaStore.Files.FileColumns.MEDIA_TYPE}=?) $AND ${MediaStore.MediaColumns.SIZE}>0"
        private val SELECTION_ALL_ARGS = arrayOf("${MediaStore.Files.FileColumns.MEDIA_TYPE_IMAGE}", "${MediaStore.Files.FileColumns.MEDIA_TYPE_VIDEO}")

        // === params for album ALL && showSingleMediaType: true ===
        private const val SELECTION_ALL_FOR_SINGLE_MEDIA_TYPE = "${MediaStore.Files.FileColumns.MEDIA_TYPE}=? $AND ${MediaStore.MediaColumns.SIZE}>0"
        private fun getSelectionArgsForSingleMediaType(mediaType: Int) = arrayOf(mediaType.toString())
        // =========================================================

        // === params for ordinary album && showSingleMediaType: false ===
        private const val SELECTION_ALBUM = "(${MediaStore.Files.FileColumns.MEDIA_TYPE}=? $OR ${MediaStore.Files.FileColumns.MEDIA_TYPE}=?) $AND $COLUMN_BUCKET_ID=? $AND ${MediaStore.MediaColumns.SIZE}>0"
        private fun getSelectionAlbumArgs(albumId: String) = arrayOf("${MediaStore.Files.FileColumns.MEDIA_TYPE_IMAGE}", "${MediaStore.Files.FileColumns.MEDIA_TYPE_VIDEO}", albumId)
        // ===============================================================

        // === params for ordinary album && showSingleMediaType: true ===
        private const val SELECTION_ALBUM_FOR_SINGLE_MEDIA_TYPE = "${MediaStore.Files.FileColumns.MEDIA_TYPE}=? $AND $COLUMN_BUCKET_ID=? $AND ${MediaStore.MediaColumns.SIZE}>0"
        private fun getSelectionAlbumArgsForSingleMediaType(mediaType: Int, albumId: String) = arrayOf(mediaType.toString(), albumId)
        // ===============================================================

        // === params for album ALL && showSingleMediaType: true && MineType=="image/gif"
        private const val SELECTION_ALL_FOR_GIF = "${MediaStore.Files.FileColumns.MEDIA_TYPE}=? $AND ${MediaStore.MediaColumns.MIME_TYPE}=? $AND ${MediaStore.MediaColumns.SIZE}>0"
        private val SELECTION_ARGS_FOR_GIF_TYPE = arrayOf("${MediaStore.Files.FileColumns.MEDIA_TYPE_IMAGE}", "image/gif")
        // ===============================================================

        // === params for ordinary album && showSingleMediaType: true  && MineType=="image/gif" ===
        private const val SELECTION_ALBUM_FOR_GIF = "${MediaStore.Files.FileColumns.MEDIA_TYPE}=? $AND $COLUMN_BUCKET_ID=? $AND ${MediaStore.MediaColumns.MIME_TYPE}=? $AND ${MediaStore.MediaColumns.SIZE}>0"
        private fun getSelectionAlbumArgsForGifType(albumId: String) = arrayOf("${MediaStore.Files.FileColumns.MEDIA_TYPE_IMAGE}", albumId, "image/gif")
        // ===============================================================

        fun with(context: Context, albumId: String, isAll: Boolean, capture: Boolean): CursorLoader {
            val selection: String
            val selectionArgs: Array<String>
            if (isAll) {
                when {
                    SelectionSpec.with().onlyShowGif() -> {
                        selection = SELECTION_ALL_FOR_GIF
                        selectionArgs = SELECTION_ARGS_FOR_GIF_TYPE
                    }
                    SelectionSpec.with().onlyShowImages() -> {
                        selection = SELECTION_ALL_FOR_SINGLE_MEDIA_TYPE
                        selectionArgs = getSelectionArgsForSingleMediaType(MediaStore.Files.FileColumns.MEDIA_TYPE_IMAGE)
                    }
                    SelectionSpec.with().onlyShowVideos() -> {
                        selection = SELECTION_ALL_FOR_SINGLE_MEDIA_TYPE
                        selectionArgs = getSelectionArgsForSingleMediaType(MediaStore.Files.FileColumns.MEDIA_TYPE_VIDEO)
                    }
                    else -> {
                        selection = SELECTION_ALL
                        selectionArgs = SELECTION_ALL_ARGS
                    }
                }
            } else {
                when {
                    SelectionSpec.with().onlyShowGif() -> {
                        selection = SELECTION_ALBUM_FOR_GIF
                        selectionArgs = getSelectionAlbumArgsForGifType(albumId)
                    }
                    SelectionSpec.with().onlyShowImages() -> {
                        selection = SELECTION_ALBUM_FOR_SINGLE_MEDIA_TYPE
                        selectionArgs = getSelectionAlbumArgsForSingleMediaType(MediaStore.Files.FileColumns.MEDIA_TYPE_IMAGE, albumId)
                    }
                    SelectionSpec.with().onlyShowVideos() -> {
                        selection = SELECTION_ALBUM_FOR_SINGLE_MEDIA_TYPE
                        selectionArgs = getSelectionAlbumArgsForSingleMediaType(MediaStore.Files.FileColumns.MEDIA_TYPE_VIDEO, albumId)
                    }
                    else -> {
                        selection = SELECTION_ALBUM
                        selectionArgs = getSelectionAlbumArgs(albumId)
                    }
                }
            }
            return AlbumMediaLoader(context, selection, selectionArgs, capture)
        }
    }

    override fun loadInBackground(): Cursor? {
        val result = super.loadInBackground()
        if (!isCapture || !hasCameraFeature()) {
            return result
        }
        val dummy = MatrixCursor(PROJECTION)
        dummy.addRow(arrayOf(MediaEntity.ITEM_ID_CAPTURE, MediaEntity.ITEM_DISPLAY_NAME_CAPTURE, "", 0, 0))
        return MergeCursor(arrayOf(dummy, result))
    }
}